/* ****************************************************************************
 *
 * Copyright (c) Microsoft Corporation. 
 *
 * This source code is subject to terms and conditions of the Microsoft Public License. A 
 * copy of the license can be found in the License.html file at the root of this distribution. If 
 * you cannot locate the  Microsoft Public License, please send an email to 
 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Microsoft Public License.
 *
 * You must not remove this notice, or any other, from this software.
 *
 * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
 * PARTICULAR PURPOSE.
 * ***************************************************************************/


#include "stdafx.h"
#include <pgl/core/PGLCoord2D.h>
#include <pgl/core/PGLArchive.h>

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif


PGL_IMPLEMENT_DYNCREATE(CPGLCoord2D, CPGLNode);

CString CPGLCoord2D::Coord2DTypeToString(ECoord2DType eCoord2DType)
{
	CString str;

	switch(eCoord2DType)
	{
	case Coord2DNorm:
		str=_T("norm");
		break;
	case Coord2DNormClip:
		str=_T("normclip");
		break;
	case Coord2DBB:
		str=_T("screen");
		break;
	default :
		str=_T("world");
		break;
	}

	return str;
}

CPGLCoord2D::ECoord2DType CPGLCoord2D::StringToCoord2DType(LPCTSTR szCoord2DType)
{
	CString str=szCoord2DType;
	str.MakeLower();

	if (str == _T("norm"))
		return Coord2DNorm;
	else if (str == _T("normclip"))
		return Coord2DNormClip;
	else if (str == _T("screen"))
		return Coord2DBB;
	else 
		return Coord2DWorld;
}

//! Save settings
void CPGLCoord2D::SerializeXML(CPGLArchive& ar)
{
	static const TCHAR szTag[] = _T("CPGLCoord2D");
	static CString str;

	markup::CMarkupArchive& xml = *((markup::CMarkupArchive*)ar.GetMarkup());
	if(ar.IsStoring())
	{
		xml.AddChildElem(szTag);
		xml.IntoElem();
			

			xml.AddChildElem(_T("Type"),Coord2DTypeToString(m_ePosType));

			xml.AddChildElem(_T("Position"));
			xml.IntoElem();
				xml.AddChildElemEx(_T("X"),m_sPos.x);
				xml.AddChildElemEx(_T("Y"),m_sPos.y);
			xml.OutOfElem();

			xml.AddChildElem(_T("Translation"));
			xml.IntoElem();
				xml.AddChildElem(_T("World"));
				xml.IntoElem();
					xml.AddChildElemEx(_T("X"),m_sWorldTrans.x);
					xml.AddChildElemEx(_T("Y"),m_sWorldTrans.y);
				xml.OutOfElem();

				xml.AddChildElem(_T("Norm"));
				xml.IntoElem();
					xml.AddChildElemEx(_T("X"),m_sNormTrans.x);
					xml.AddChildElemEx(_T("Y"),m_sNormTrans.y);
				xml.OutOfElem();

				xml.AddChildElem(_T("NormClip"));
				xml.IntoElem();
					xml.AddChildElemEx(_T("X"),m_sNormClipTrans.x);
					xml.AddChildElemEx(_T("Y"),m_sNormClipTrans.y);
				xml.OutOfElem();

				xml.AddChildElem(_T("Screen"));
				xml.IntoElem();
					xml.AddChildElemEx(_T("X"),m_sBBTrans.x);
					xml.AddChildElemEx(_T("Y"),m_sBBTrans.y);
				xml.OutOfElem();

			xml.OutOfElem();

		xml.OutOfElem();
	}
	else
	{
		// first try to find graph with same name otherwize get first one...
		if  (!xml.FindChildElem(szTag))
				return;
		xml.IntoElem();

			/////////////////////////////////////////////////////////
			if (xml.FindChildElem(_T("Type")))
			{
				str=xml.GetChildData();
				m_ePosType=StringToCoord2DType(str);
			}

			xml.ResetChildPos();
			if(xml.FindChildElem(_T("Position")))
			{
				xml.IntoElem();
					if (xml.FindChildElem(_T("X")))
						m_sPos.x=xml.GetChildDataDouble();
					if (xml.FindChildElem(_T("Y")))
						m_sPos.y=xml.GetChildDataDouble();
				xml.OutOfElem();
			}

			xml.ResetChildPos();
			if(xml.FindChildElem(_T("Translation")))
			{
				xml.IntoElem();
					if(xml.FindChildElem(_T("World")))
					{
						xml.IntoElem();
							if(xml.FindChildElem(_T("X")))
								m_sWorldTrans.x=xml.GetChildDataDouble();
							xml.ResetChildPos();
							if(xml.FindChildElem(_T("Y")))
								m_sWorldTrans.y=xml.GetChildDataDouble();
						xml.OutOfElem();
					}	
	
					xml.ResetChildPos();
					if (xml.FindChildElem(_T("Norm")))
					{
						xml.IntoElem();
							if (xml.FindChildElem(_T("X")))
								m_sNormTrans.x=xml.GetChildDataDouble();

							xml.ResetChildPos();
							if (xml.FindChildElem(_T("Y")))
								m_sNormTrans.y=xml.GetChildDataDouble();
						xml.OutOfElem();
					}

					xml.ResetChildPos();
					if (xml.FindChildElem(_T("NormClip")))
					{
						xml.IntoElem();
							if (xml.FindChildElem(_T("X")))
								m_sNormClipTrans.x=xml.GetChildDataDouble();

							xml.ResetChildPos();
							if (xml.FindChildElem(_T("Y")))
								m_sNormClipTrans.y=xml.GetChildDataDouble();
						xml.OutOfElem();
					}

					xml.ResetChildPos();
					if (xml.FindChildElem(_T("Screen")))
					{
						xml.IntoElem();
							if (xml.FindChildElem(_T("X")))
								m_sBBTrans.x=xml.GetChildDataDouble();

							xml.ResetChildPos();
							if (xml.FindChildElem(_T("Y")))
								m_sBBTrans.y=xml.GetChildDataDouble();
						xml.OutOfElem();
					}
				xml.OutOfElem();
			}

		xml.OutOfElem();
	}
}


#ifdef _DEBUG
void CPGLCoord2D::Dump( CDumpContext& dc ) const
{
    // call base class function first
    CObject::Dump( dc );
}
void CPGLCoord2D::AssertValid() const
{
} 
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CPGLCoord2D::CPGLCoord2D(double _x, double _y, ECoord2DType eType)
: m_ePosType(eType), m_sBBTrans(0,0), m_sNormTrans(0,0),m_sNormClipTrans(0,0), m_sWorldTrans(0,0), m_sPos(_x,_y)
{

}

CPGLCoord2D& CPGLCoord2D::operator = (const CPGLCoord2D& c)
{
	if (this != &c)
	{
		m_ePosType = c.m_ePosType;
		m_sPos = c.m_sPos;
		m_sBBTrans = c.m_sBBTrans;
		m_sNormTrans = c.m_sNormTrans;
		m_sNormClipTrans = c.m_sNormClipTrans;
		m_sWorldTrans = c.m_sWorldTrans;
	}
	return *this;
}


CPGLCoord2D::~CPGLCoord2D()
{

}

gfxinterface::SPointD CPGLCoord2D::GetWorldPosition(const gfxinterface::CGfxInterface& gfx) const
{
	gfxinterface::SPointD pos;

	switch (m_ePosType)
	{
	case Coord2DWorld:
		pos = m_sPos;
		break;
	case Coord2DNorm:
		pos.x = gfx.NormBBoxToWorldx(m_sPos.x); 
		pos.y = gfx.NormBBoxToWorldy(m_sPos.y); 
		break;
	case Coord2DNormClip:
		pos.x = gfx.NormClipBBoxToWorldx(m_sPos.x); 
		pos.y = gfx.NormClipBBoxToWorldy(m_sPos.y); 
		break;
	case Coord2DBB:
		pos.x = gfx.BBToWorldx(m_sPos.x); 
		pos.y = gfx.BBToWorldy(m_sPos.y); 
		break;
	}

	// updating with translations
	// World...
	if (m_sWorldTrans.x)
		pos.x+=m_sWorldTrans.x;
	if (m_sWorldTrans.y)
		pos.y+=m_sWorldTrans.y;

	// norm
	if (m_sNormTrans.x)
		pos.x+=gfx.NormBBoxToWorldAbsx(m_sNormTrans.x);
	if (m_sNormTrans.y)
		pos.y+=gfx.NormBBoxToWorldAbsy(m_sNormTrans.y);

	// norm clip
	if (m_sNormClipTrans.x)
		pos.x+=gfx.NormClipBBoxToWorldAbsx(m_sNormClipTrans.x);
	if (m_sNormClipTrans.y)
		pos.y+=gfx.NormClipBBoxToWorldAbsy(m_sNormClipTrans.y);

	// pixels
	if (m_sBBTrans.x)
		pos.x+=gfx.BBToWorldAbsx(m_sBBTrans.x);
	if (m_sBBTrans.y)
		pos.y+=gfx.BBToWorldAbsy(m_sBBTrans.y);

	return pos;
};

gfxinterface::SPointD CPGLCoord2D::GetScreenPosition(const gfxinterface::CGfxInterface& gfx) const
{
	gfxinterface::SPointD pos;

	switch (m_ePosType)
	{
	case Coord2DWorld:
		pos.x = gfx.WorldToBBx(m_sPos.x); 
		pos.y = gfx.WorldToBBy(m_sPos.y); 
		break;
	case Coord2DNorm:
		pos.x = gfx.NormBBoxToBBx(m_sPos.x); 
		pos.y = gfx.NormBBoxToBBy(m_sPos.y); 
		break;
	case Coord2DNormClip:
		pos.x = gfx.NormClipBBoxToBBx(m_sPos.x); 
		pos.y = gfx.NormClipBBoxToBBy(m_sPos.y); 
		break;
	case Coord2DBB:
		pos = m_sPos;
		break;
	}

	// updating with translations
	// World...
	if (m_sWorldTrans.x)
		pos.x+=gfx.WorldToBBAbsx(m_sWorldTrans.x);
	if (m_sWorldTrans.y)
		pos.y+=gfx.WorldToBBAbsx(m_sWorldTrans.y);

	// norm
	if (m_sNormTrans.x)
		pos.x+=gfx.NormBBoxToBBAbsx(m_sNormTrans.x);
	if (m_sNormTrans.y)
		pos.y+=gfx.NormBBoxToBBAbsx(m_sNormTrans.y);

	// norm clip
	if (m_sNormClipTrans.x)
		pos.x+=gfx.NormClipBBoxToBBAbsx(m_sNormClipTrans.x);
	if (m_sNormClipTrans.y)
		pos.y+=gfx.NormClipBBoxToBBAbsx(m_sNormClipTrans.y);

	// pixels
	if (m_sBBTrans.x)
		pos.x+=m_sBBTrans.x;
	if (m_sBBTrans.y)
		pos.y+=m_sBBTrans.y;

	return pos;
};
